/*=========================================================================================================

                        EDIT HISTORY FOR MODULE

  This section contains comments describing changes made to the module.
  Notice that changes are listed in reverse chronological order.


when         who             what, where, why
----------   -----------     ----------------------------------------------------------
04/02/2024   Forester        创建文件, 并完成 GPIO_SetBits, GPIO_ResetBits, GPIO_Init 三
                             个函数, 目的是为了尽可能的模仿 ST 官方提供的标准库, 学习如何对
                             寄存器进行封装.



=========================================================================================================*/
#include "stm32f4xx_gpio.h"

/************************************************************************************************************
* Function name : GPIO_SetBits
* Description   : 将 GPIOx 外设的 GPIO_Pin 引脚设置为高电平
* Parameter     : GPIOx [In]    - Gpio 外设
                  GPIO_Pin [In] - GPIO_Pin 引脚, 取值范围为 GPIO_Pin_x,  0 <= x <= 15, 可以使用 | 组合设置
* Return        : 
************************************************************************************************************/
void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->BSRRL = GPIO_Pin;
}


/************************************************************************************************************
* Function name : GPIO_ResetBits
* Description   : 将 GPIOx 外设的 GPIO_Pin 引脚设置为低电平
* Parameter     : GPIOx    [In]    - Gpio 外设
                  GPIO_Pin [In] - GPIO_Pin 引脚, 取值范围为 GPIO_Pin_x,  0 <= x <= 15, 可以使用 | 组合设置
* Return        : 
************************************************************************************************************/
void GPIO_ResetBits(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->BSRRH = GPIO_Pin;
}


/************************************************************************************************************
* Function name : GPIO_Init
* Description   : 初始化 GPIO 配置
* Parameter     : GPIOx    [In]    - Gpio 外设
                  GPIO_Pin [In] - GPIO_Pin 引脚, 取值范围为 GPIO_Pin_x,  0 <= x <= 15, 可以使用 | 组合设置
* Return        : 
************************************************************************************************************/
void GPIO_Init(GPIO_TypeDef *GPIOx, const GPIO_InitTypedef *GPIO_InitStruct)
{
    uint16_t pins = GPIO_InitStruct->GPIO_Pin;
    uint16_t bits = 0;
    while(pins != 0)
    {
        if(pins & 1)
        {
            GPIOx->MODER &= ~(0x03 << (2*bits));
            GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (2 * bits));
        
            GPIOx->PUPDR &= ~(0x03 << (2*bits));
            GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (2 * bits));

            /* 输出模式 或 复用输出, 才需要配置推挽, 开漏, 输出速度 */
            if((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_Out) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
            {
                GPIOx->OTYPER &= ~(1 << bits);
                GPIOx->OTYPER |= (((uint16_t)GPIO_InitStruct->GPIO_OType) << bits);

                GPIOx->OSPEEDR &= ~(0x03 << (2 * bits));
                GPIOx->OSPEEDR |= (((uint32_t)GPIO_InitStruct->GPIO_Speed) << (2 * bits));
            }
        }
        pins >>= 1;
        bits++;
    }
}
